#import "FlutterPanglePlugin.h"
#import "DetailFragmentFactory.h"
#import <Flutter/Flutter.h>
#import <PAGSShortPlay/PAGSShortPlay.h>

// 用于预热的全局对象以及Fragment管理
static PAGSDetailFragment *_warmUpFragment = nil;
static BOOL _warmUpInProgress = NO;
static NSMutableDictionary<NSNumber*, PAGSDetailFragment*> *_fragmentInfo = nil;

@interface WarmUpDelegate : NSObject <PAGSDetailFragmentDelegate, PAGSAdDelegate>
@end

@implementation WarmUpDelegate
- (BOOL)detailFragmentShortPlay:(PAGSShort *)shortPlay needBlockAtIndex:(int)index { return NO; }
- (void)detailFragmentShortPlay:(PAGSShort *)shortPlay showAdIfNeedAtIndex:(int)index unlockListener:(PAGSPlayBlockResultListener *)listener {}
@end

static WarmUpDelegate *_warmUpDelegate = nil;

static UIWindow *FlutterPanglePluginGetKeyWindow(void) {
  UIWindow *keyWindow = nil;
  if (@available(iOS 13.0, *)) {
    NSSet<UIScene *> *scenes = [UIApplication sharedApplication].connectedScenes;
    for (UIScene *scene in scenes) {
      if (scene.activationState == UISceneActivationStateForegroundActive &&
          [scene isKindOfClass:[UIWindowScene class]]) {
        UIWindowScene *windowScene = (UIWindowScene *)scene;
        for (UIWindow *window in windowScene.windows) {
          if (window.isKeyWindow) {
            keyWindow = window;
            break;
          }
        }
      }
      if (keyWindow) { break; }
    }
  } else {
    keyWindow = [UIApplication sharedApplication].keyWindow;
  }
  if (!keyWindow) {
    keyWindow = [UIApplication sharedApplication].windows.firstObject;
  }
  return keyWindow;
}

@implementation FlutterPanglePlugin
+ (void)initialize {
  if (self == [FlutterPanglePlugin class]) {
    _fragmentInfo = [NSMutableDictionary dictionary];
    [FlutterPanglePlugin logText:@"[PanglePlugin] initialize fragmentInfo"];
  }
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  FlutterMethodChannel* channel = [FlutterMethodChannel
      methodChannelWithName:@"flutter_pangle"
            binaryMessenger:[registrar messenger]];
  FlutterPanglePlugin* instance = [[FlutterPanglePlugin alloc] init];
  [registrar addMethodCallDelegate:instance channel:channel];
  
  // Register PlatformView factory
  DetailFragmentFactory* factory = [[DetailFragmentFactory alloc] initWithMessenger:[registrar messenger]];
  [registrar registerViewFactory:factory withId:@"flutter_pangle/detail_fragment"];
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  if ([@"initializeSDK" isEqualToString:call.method]) {
    [self initializeSDK:call result:result];
  } else if ([@"setEligibleAudience" isEqualToString:call.method]) {
    [self setEligibleAudience:call result:result];
  } else if ([@"setContentLanguage" isEqualToString:call.method]) {
    [self setContentLanguage:call result:result];
  } else if ([@"setContentLanguages" isEqualToString:call.method]) {
    [self setContentLanguages:call result:result];
  } else if ([@"requestFeedList" isEqualToString:call.method]) {
    [self requestFeedList:call result:result];
  } else if ([@"requestFeedListWithFilters" isEqualToString:call.method]) {
    [self requestFeedListWithFilters:call result:result];
  } else if ([@"requestPopularDrama" isEqualToString:call.method]) {
    [self requestPopularDrama:call result:result];
  } else if ([@"requestNewFeedList" isEqualToString:call.method]) {
    [self requestNewFeedList:call result:result];
  } else if ([@"requestDramaWithTag" isEqualToString:call.method]) {
    [self requestDramaWithTag:call result:result];
  } else if ([@"getCategoryList" isEqualToString:call.method]) {
    [self getCategoryList:call result:result];
  } else if ([@"requestSearchDrama" isEqualToString:call.method]) {
    [self requestSearchDrama:call result:result];
  } else if ([@"checkPlayStatus" isEqualToString:call.method]) {
    [self checkPlayStatus:result];
  } else if ([@"setCollected" isEqualToString:call.method]) {
    [self setCollected:call result:result];
  } else if ([@"clearLocalCache" isEqualToString:call.method]) {
    [self clearLocalCache:result];
  } else if ([@"getCurrentLanguage" isEqualToString:call.method]) {
    result(pags_get_current_language());
  } else if ([@"warmUpPlayerEngine" isEqualToString:call.method]) {
    [self warmUpPlayerEngine:result];
  } else {
    result(FlutterMethodNotImplemented);
  }
}

#pragma mark - SDK初始化
- (void)initializeSDK:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSString* appId = args[@"appId"];
  NSString* vodAppId = args[@"vodAppId"];
  NSString* securityKey = args[@"securityKey"];
  NSString* licenseAssertPath = args[@"licenseAssertPath"];
  
  if (!appId || !vodAppId || !securityKey || !licenseAssertPath) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing required parameters"
                               details:nil]);
    return;
  }
  
  PAGSSDKConfig* config = [[PAGSSDKConfig alloc] initWithAppid:appId
                                                      vodAppId:vodAppId
                                                   securityKey:securityKey
                                            licenseAssertPath:licenseAssertPath];
  
  id userIdObj = args[@"userId"];
  if ([userIdObj isKindOfClass:[NSString class]]) {
    NSString* userId = (NSString*)userIdObj;
    if (userId.length > 0) {
      [config setAppUserId:userId];
    }
  }
  
  NSNumber* debug = args[@"debug"];
  if (debug && [debug boolValue]) {
    [config setSDKDebug:YES];
  }
  
  // 必须设置为YES,否则观看短剧
  [PAGSSDK setEligibleAudience:YES];
  
  // 使用pags_get_current_language()获取设备当前语言
  [PAGSSDK setContentLanguage:pags_get_current_language()];
  
  [PAGSSDK startWithConfig:config completionHandler:^(BOOL success, NSError * _Nullable error) {
    if (success) {
      result(@YES);
    } else {
      NSDictionary* details = error ? @{@"code": @(error.code)} : @{@"code": @(-1)};
      result([FlutterError errorWithCode:@"INIT_FAILED"
                                 message:error.localizedDescription ?: @"SDK initialization failed"
                                 details:details]);
    }
  }];
}

#pragma mark - 合规设置
- (void)setEligibleAudience:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSNumber* eligible = args[@"eligible"];
  if (!eligible) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing eligible parameter"
                               details:nil]);
    return;
  }
  [PAGSSDK setEligibleAudience:[eligible boolValue]];
  result(nil);
}

#pragma mark - 设置内容语言（单个）
- (void)setContentLanguage:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSString* language = args[@"language"];
  if (!language) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing language parameter"
                               details:nil]);
    return;
  }
  [PAGSSDK setContentLanguage:language];
  result(nil);
}

#pragma mark - 设置内容语言（多个）
- (void)setContentLanguages:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSArray* languages = args[@"languages"];
  if (!languages) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing languages parameter"
                               details:nil]);
    return;
  }
  [PAGSSDK setContentLanguages:languages];
  result(nil);
}

#pragma mark - 获取默认短剧列表
- (void)requestFeedList:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSNumber* indexNum = args[@"index"];
  NSNumber* countNum = args[@"count"];
  
  if (!indexNum || !countNum) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing index or count parameter"
                               details:nil]);
    return;
  }
  
  int index = [indexNum intValue];
  int count = [countNum intValue];
  
  [PAGSSDK requestFeedListWithIndex:index count:count completionHandler:^(NSArray<PAGSShort *> * _Nullable list, BOOL hasMore, NSError * _Nullable error) {
    if (error) {
      result([self createErrorResponse:error]);
    } else {
      result([self createFeedListResponse:list ?: @[] hasMore:hasMore]);
    }
  }];
}

#pragma mark - 获取指定分类或短剧的列表
- (void)requestFeedListWithFilters:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSNumber* indexNum = args[@"index"];
  NSNumber* countNum = args[@"count"];
  
  if (!indexNum || !countNum) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing index or count parameter"
                               details:nil]);
    return;
  }
  
  int index = [indexNum intValue];
  int count = [countNum intValue];
  
  id categoryIdsObj = args[@"categoryIds"];
  NSArray* categoryIds = ([categoryIdsObj isKindOfClass:[NSArray class]]) ? categoryIdsObj : @[];
  
  id shortplayIdsObj = args[@"shortplayIds"];
  NSArray* shortplayIds = ([shortplayIdsObj isKindOfClass:[NSArray class]]) ? shortplayIdsObj : @[];
  
  NSMutableArray* categoryIdArray = [NSMutableArray array];
  for (NSNumber* num in categoryIds) {
    [categoryIdArray addObject:num];
  }
  
  NSMutableArray* shortplayIdArray = [NSMutableArray array];
  for (NSNumber* num in shortplayIds) {
    [shortplayIdArray addObject:num];
  }
  
  [PAGSSDK requestFeedListWithIndex:index count:count categoryIds:categoryIdArray shortplayIds:shortplayIdArray completionHandler:^(NSArray<PAGSShort *> * _Nullable list, BOOL hasMore, NSError * _Nullable error) {
    if (error) {
      result([self createErrorResponse:error]);
    } else {
      result([self createFeedListResponse:list ?: @[] hasMore:hasMore]);
    }
  }];
}

#pragma mark - 获取热门短剧列表
- (void)requestPopularDrama:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSNumber* indexNum = args[@"index"];
  NSNumber* countNum = args[@"count"];
  
  if (!indexNum || !countNum) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing index or count parameter"
                               details:nil]);
    return;
  }
  
  int index = [indexNum intValue];
  int count = [countNum intValue];
  
  [PAGSSDK requestPopularDrama:index count:count completionHandler:^(NSArray<PAGSShort *> * _Nullable list, BOOL hasMore, NSError * _Nullable error) {
    if (error) {
      result([self createErrorResponse:error]);
    } else {
      result([self createFeedListResponse:list ?: @[] hasMore:hasMore]);
    }
  }];
}

#pragma mark - 获取新剧列表
- (void)requestNewFeedList:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSNumber* indexNum = args[@"index"];
  NSNumber* countNum = args[@"count"];
  
  if (!indexNum || !countNum) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing index or count parameter"
                               details:nil]);
    return;
  }
  
  int index = [indexNum intValue];
  int count = [countNum intValue];
  
  [PAGSSDK requestNewFeedListWithIndex:index count:count completionHandler:^(NSArray<PAGSShort *> * _Nullable list, BOOL hasMore, NSError * _Nullable error) {
    if (error) {
      result([self createErrorResponse:error]);
    } else {
      result([self createFeedListResponse:list ?: @[] hasMore:hasMore]);
    }
  }];
}

#pragma mark - 获取指定标签的列表
- (void)requestDramaWithTag:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSNumber* tagNum = args[@"tag"];
  NSNumber* indexNum = args[@"index"];
  NSNumber* countNum = args[@"count"];
  
  if (!tagNum || !indexNum || !countNum) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing tag, index or count parameter"
                               details:nil]);
    return;
  }
  
  PAGSShortTag tag = [tagNum intValue];
  int index = [indexNum intValue];
  int count = [countNum intValue];
  
  [PAGSSDK requestDramaWithTag:tag index:index count:count completionHandler:^(NSArray<PAGSShort *> * _Nullable list, BOOL hasMore, NSError * _Nullable error) {
    if (error) {
      result([self createErrorResponse:error]);
    } else {
      result([self createFeedListResponse:list ?: @[] hasMore:hasMore]);
    }
  }];
}

#pragma mark - 获取短剧分类列表
- (void)getCategoryList:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSString* language = args[@"language"];
  
  if (!language) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing language parameter"
                               details:nil]);
    return;
  }
  
  [PAGSSDK getCategoryListWithLanguage:language completionHandler:^(NSArray<PAGSCategoryItem *> * _Nullable categoryList, NSString *language, NSError * _Nullable error) {
    if (error) {
      result([FlutterError errorWithCode:@"GET_CATEGORY_FAILED"
                                 message:error.localizedDescription
                                 details:@{@"code": @(error.code)}]);
    } else {
      NSMutableArray* list = [NSMutableArray array];
      for (PAGSCategoryItem* item in categoryList ?: @[]) {
        [list addObject:[self convertCategoryItemToMap:item]];
      }
      result(list);
    }
  }];
}

#pragma mark - 搜索短剧
- (void)requestSearchDrama:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSNumber* indexNum = args[@"index"];
  NSNumber* countNum = args[@"count"];
  NSString* keyword = args[@"keyword"];
  NSNumber* isFuzzyNum = args[@"isFuzzy"];
  
  if (!indexNum || !countNum || !keyword || !isFuzzyNum) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing required parameters"
                               details:nil]);
    return;
  }
  
  int index = [indexNum intValue];
  int count = [countNum intValue];
  BOOL isFuzzy = [isFuzzyNum boolValue];
  
  [PAGSSDK requestSearchDrama:index count:count keyWord:keyword isFuzzy:isFuzzy completionHandler:^(NSArray<PAGSShort *> * _Nullable list, BOOL hasMore, NSError * _Nullable error) {
    if (error) {
      result([self createErrorResponse:error]);
    } else {
      result([self createFeedListResponse:list ?: @[] hasMore:hasMore]);
    }
  }];
}

#pragma mark - 检查当前地区是否支持播放
- (void)checkPlayStatus:(FlutterResult)result {
  [PAGSSDK checkPlayStatusCompletionHandler:^(PAGSAvailable available, NSError * _Nullable error) {
    if (error) {
      result([FlutterError errorWithCode:@"CHECK_PLAY_STATUS_FAILED"
                                 message:error.localizedDescription
                                 details:@{@"code": @(error.code)}]);
    } else {
      // PAGSAvailable: 0=未知, 1=支持, 2=不支持, 3=错误
      result(@(available));
    }
  }];
}

#pragma mark - 设置收藏状态
- (void)setCollected:(FlutterMethodCall*)call result:(FlutterResult)result {
  NSDictionary* args = call.arguments;
  NSNumber* collectedNum = args[@"collected"];
  NSNumber* shortplayIdNum = args[@"shortplayId"];
  
  if (!collectedNum || !shortplayIdNum) {
    result([FlutterError errorWithCode:@"INVALID_ARGUMENT"
                               message:@"Missing collected or shortplayId parameter"
                               details:nil]);
    return;
  }
  
  BOOL collected = [collectedNum boolValue];
  long shortplayId = [shortplayIdNum longValue];
  
  [PAGSSDK setCollected:collected withShortplayId:shortplayId completionHandler:^(BOOL success, NSError * _Nullable error) {
    if (error) {
      result([FlutterError errorWithCode:@"SET_COLLECTED_FAILED"
                                 message:error.localizedDescription
                                 details:@{@"code": @(error.code)}]);
    } else {
      result(@(success));
    }
  }];
}

#pragma mark - 清除本地缓存
- (void)clearLocalCache:(FlutterResult)result {
  [PAGSSDK clearLocalCache];
  result(nil);
}

#pragma mark - 辅助方法：转换PAGSShort为Map
+ (NSDictionary*)convertShortToMap:(PAGSShort*)drama {
  NSMutableDictionary* map = [NSMutableDictionary dictionary];
  map[@"title"] = drama.title ?: @"";
  map[@"desc"] = drama.desc ?: @"";
  map[@"expireTime"] = @(drama.play_url_expire_time);
  map[@"id"] = @(drama.shortplay_id);
  map[@"total"] = @(drama.total);
  map[@"progress_state"] = @(drama.progress_state);
  map[@"firstOnlineTime"] = @(drama.first_online_time);
  if (drama.category && [drama.category isKindOfClass:[NSDictionary class]]) {
    NSDictionary *categoryDict = (NSDictionary *)drama.category;
    NSMutableArray *categoryArray = [NSMutableArray array];
    
    // 遍历字典，key是分类ID，value是分类名称
    for (id key in categoryDict) {
      id value = categoryDict[key];
      NSMutableDictionary *categoryMap = [NSMutableDictionary dictionary];
      
      // 处理key（分类ID）
      if ([key isKindOfClass:[NSNumber class]]) {
        categoryMap[@"id"] = key;
      } else if ([key isKindOfClass:[NSString class]]) {
        // 如果是字符串，尝试转换为数字
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        NSNumber *categoryId = [formatter numberFromString:(NSString *)key];
        if (categoryId) {
          categoryMap[@"id"] = categoryId;
        } else {
          categoryMap[@"id"] = @0;
        }
      } else {
        categoryMap[@"id"] = @0;
      }
      
      // 处理value（分类名称）
      if ([value isKindOfClass:[NSString class]]) {
        categoryMap[@"name"] = value;
      } else if (value) {
        categoryMap[@"name"] = [value description];
      }
      
      [categoryArray addObject:categoryMap];
    }
    
    if (categoryArray.count > 0) {
      map[@"categories"] = categoryArray;
    }
  }
  
  if (drama.cover_image && drama.cover_image.length > 0) {
    map[@"cover_image"] = drama.cover_image;
  }
  
  if (drama.country && drama.country.length > 0) {
    map[@"country"] = drama.country;
  }
  
  if (drama.language && drama.language.length > 0) {
    map[@"language"] = drama.language;
  }
  
  if (drama.episodes && [drama.episodes isKindOfClass:[NSArray class]]) {
    NSMutableArray* episodeList = [NSMutableArray array];
    for (id episodeObj in drama.episodes) {
      if ([episodeObj isKindOfClass:[PAGSShortEpisode class]]) {
        PAGSShortEpisode* episode = (PAGSShortEpisode*)episodeObj;
        NSMutableDictionary* episodeMap = [NSMutableDictionary dictionary];
        episodeMap[@"index"] = @(episode.episode_index);
        episodeMap[@"id"] = @(episode.episode_id);
        if (episode.Vid) episodeMap[@"vid"] = episode.Vid;
        if (episode.play_auth_token) episodeMap[@"play_auth_token"] = episode.play_auth_token;
        episodeMap[@"EnableAdaptive"] = @(episode.EnableAdaptive);
        episodeMap[@"version"] = @(episode.version);
        episodeMap[@"status"] = @(episode.status);
        episodeMap[@"Duration"] = @(episode.Duration);
        episodeMap[@"expireTime"] = @(episode.play_url_expire_absolute_time);
        if (episode.user_like_info) {
          episodeMap[@"isLiked"] = @(episode.user_like_info.count);
        }
        if (episode.total_like_info) {
          episodeMap[@"totalLikeCount"] = @(episode.total_like_info.count);
        }
        // PlayInfoList 可能包含自定义对象，需要转换为字典数组
        if (episode.PlayInfoList && [episode.PlayInfoList isKindOfClass:[NSArray class]]) {
          NSMutableArray* playInfoList = [NSMutableArray array];
          for (id playInfoObj in episode.PlayInfoList) {
            if ([playInfoObj isKindOfClass:[PAGSShortPlay class]]) {
              PAGSShortPlay* playInfo = (PAGSShortPlay*)playInfoObj;
              NSMutableDictionary* playInfoMap = [NSMutableDictionary dictionary];
              if (playInfo.FileId) playInfoMap[@"FileId"] = playInfo.FileId;
              if (playInfo.Md5) playInfoMap[@"Md5"] = playInfo.Md5;
              if (playInfo.MainPlayUrl) playInfoMap[@"MainPlayUrl"] = playInfo.MainPlayUrl;
              if (playInfo.BackupPlayUrl) playInfoMap[@"BackupPlayUrl"] = playInfo.BackupPlayUrl;
              if (playInfo.PlayAuthId) playInfoMap[@"PlayAuthId"] = playInfo.PlayAuthId;
              if (playInfo.PlayAuth) playInfoMap[@"PlayAuth"] = playInfo.PlayAuth;
              if (playInfo.Definition) playInfoMap[@"Definition"] = playInfo.Definition;
              if (playInfo.FileType) playInfoMap[@"FileType"] = playInfo.FileType;
              if (playInfo.Format) playInfoMap[@"Format"] = playInfo.Format;
              if (playInfo.Codec) playInfoMap[@"Codec"] = playInfo.Codec;
              playInfoMap[@"Bitrate"] = @(playInfo.Bitrate);
              playInfoMap[@"Width"] = @(playInfo.Width);
              playInfoMap[@"Height"] = @(playInfo.Height);
              playInfoMap[@"Size"] = @(playInfo.Size);
              playInfoMap[@"Duration"] = @(playInfo.Duration);
              if (playInfo.KeyFrameAlignment) playInfoMap[@"KeyFrameAlignment"] = playInfo.KeyFrameAlignment;
              if (playInfo.MainUrlExpire) playInfoMap[@"MainUrlExpire"] = playInfo.MainUrlExpire;
              if (playInfo.BackupUrlExpire) playInfoMap[@"BackupUrlExpire"] = playInfo.BackupUrlExpire;
              if (playInfo.Quality) playInfoMap[@"Quality"] = playInfo.Quality;
              if (playInfo.CheckInfo) playInfoMap[@"CheckInfo"] = playInfo.CheckInfo;
              if (playInfo.BarrageMaskOffset) playInfoMap[@"BarrageMaskOffset"] = playInfo.BarrageMaskOffset;
              [playInfoList addObject:playInfoMap];
            }
          }
          episodeMap[@"PlayInfoList"] = playInfoList;
          NSError *episodeJsonError = nil;
          NSData *episodeJsonData = [NSJSONSerialization dataWithJSONObject:playInfoList options:0 error:&episodeJsonError];
          if (!episodeJsonError && episodeJsonData) {
            NSString *playInfoListData = [[NSString alloc] initWithData:episodeJsonData encoding:NSUTF8StringEncoding];
            if (playInfoListData.length > 0) {
              episodeMap[@"playInfoListData"] = playInfoListData;
            }
          }
        }
        [episodeList addObject:episodeMap];
      }
    }
    map[@"episodes"] = episodeList;
  }
  
  if (drama.total_collect_info) {
    map[@"totalCollectCount"] = @(drama.total_collect_info.count);
  }
  
  if (drama.user_collect_info) {
    map[@"isCollected"] = @(drama.user_collect_info.count);
  }
  
  if (drama.tag_list && [drama.tag_list isKindOfClass:[NSArray class]]) {
    NSMutableArray* tagList = [NSMutableArray array];
    for (id tagObj in drama.tag_list) {
      if ([tagObj isKindOfClass:[PAGSShortTagInfo class]]) {
        PAGSShortTagInfo* tag = (PAGSShortTagInfo*)tagObj;
        NSMutableDictionary* tagMap = [NSMutableDictionary dictionary];
        tagMap[@"tag_id"] = @(tag.tag_id);
        if (tag.tag_name) tagMap[@"tag_name"] = tag.tag_name;
        [tagList addObject:tagMap];
      }
    }
    map[@"tags"] = tagList;
  }
  
  return map;
}

#pragma mark - 辅助方法：转换Map为PAGSShort
+ (PAGSShort*)convertMapToShort:(id)mapOrJsonString {
  NSDictionary* map = nil;
  
  // 如果是NSString类型，先解析为NSDictionary
  if ([mapOrJsonString isKindOfClass:[NSString class]]) {
    NSString* jsonString = (NSString*)mapOrJsonString;
    if (jsonString.length == 0) {
      return nil;
    }
    NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    if (!jsonData) {
      return nil;
    }
    NSError* error = nil;
    id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
    if (error || ![jsonObject isKindOfClass:[NSDictionary class]]) {
      return nil;
    }
    map = (NSDictionary*)jsonObject;
  } else if ([mapOrJsonString isKindOfClass:[NSDictionary class]]) {
    map = (NSDictionary*)mapOrJsonString;
  } else {
    return nil;
  }
  
  if (!map) {
    return nil;
  }
  
  NSMutableDictionary* sdkMap = [NSMutableDictionary dictionaryWithDictionary:map];
  
  // 字段映射：将Flutter端的字段名映射为SDK期望的字段名
  // id -> shortplay_id
  id shortplayId = map[@"id"];
  if (shortplayId) {
    sdkMap[@"shortplay_id"] = shortplayId;
  }
  
  // expireTime -> play_url_expire_time
  id expireTime = map[@"expireTime"];
  if (expireTime) {
    sdkMap[@"play_url_expire_time"] = expireTime;
  }
  
    // first_online_time -> first_online_time
    id first_online_time = map[@"firstOnlineTime"];
    if (first_online_time) {
      sdkMap[@"first_online_time"] = expireTime;
    }
    
  // categories数组 -> category字典
  id categories = map[@"categories"];
  if (categories && [categories isKindOfClass:[NSArray class]]) {
    NSArray* categoryArray = (NSArray*)categories;
    NSMutableDictionary* categoryDict = [NSMutableDictionary dictionary];
    for (id categoryObj in categoryArray) {
      if ([categoryObj isKindOfClass:[NSDictionary class]]) {
        NSDictionary* category = (NSDictionary*)categoryObj;
        id categoryId = category[@"id"];
        id categoryName = category[@"name"];
        if (categoryId && categoryName) {
          categoryDict[categoryId] = categoryName;
        }
      }
    }
    if (categoryDict.count > 0) {
      sdkMap[@"category"] = categoryDict;
    }
  }
  
  // totalCollectCount -> total_collect_info
  id totalCollectCount = map[@"totalCollectCount"];
  if (totalCollectCount) {
    // 创建 PAGSCollectInfo 对象
    NSDictionary* collectInfo = @{@"count": totalCollectCount};
    sdkMap[@"total_collect_info"] = collectInfo;
  }
  
  // isCollected -> user_collect_info
  id isCollected = map[@"isCollected"];
  if (isCollected) {
    // 创建 PAGSCollectInfo 对象
    long count = [isCollected isKindOfClass:[NSNumber class]] ? [(NSNumber*)isCollected longValue] : 0;
    NSDictionary* collectInfo = @{@"count": @(count)};
    sdkMap[@"user_collect_info"] = collectInfo;
  }
  
  // tags数组 -> tag_list数组（字段名可能需要调整，根据SDK实际需求）
  id tags = map[@"tags"];
  if (tags && [tags isKindOfClass:[NSArray class]]) {
    sdkMap[@"tag_list"] = tags;
  }
  
  // episodes数组字段映射
  id episodes = map[@"episodes"];
  if (episodes && [episodes isKindOfClass:[NSArray class]]) {
    NSArray* episodeArray = (NSArray*)episodes;
    NSMutableArray* sdkEpisodeArray = [NSMutableArray array];
    for (id episodeObj in episodeArray) {
      if ([episodeObj isKindOfClass:[NSDictionary class]]) {
        NSMutableDictionary* episode = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary*)episodeObj];
        // index -> episode_index
        if (episode[@"index"]) {
          episode[@"episode_index"] = episode[@"index"];
        }
        // id -> episode_id
        if (episode[@"id"]) {
          episode[@"episode_id"] = episode[@"id"];
        }
        // vid -> Vid (注意大小写)
        if (episode[@"vid"]) {
          episode[@"Vid"] = episode[@"vid"];
        }
        // expireTime -> play_url_expire_absolute_time
        if (episode[@"expireTime"]) {
          episode[@"play_url_expire_absolute_time"] = episode[@"expireTime"];
        }
        // 解析 playInfoListData -> PlayInfoList
        NSString *playInfoListData = nil;
        id playInfoListDataObj = episode[@"playInfoListData"];
        if ([playInfoListDataObj isKindOfClass:[NSString class]]) {
          playInfoListData = (NSString *)playInfoListDataObj;
        } else if ([playInfoListDataObj respondsToSelector:@selector(stringValue)]) {
          playInfoListData = [playInfoListDataObj stringValue];
        }
        if (playInfoListData.length > 0) {
          NSData *playInfoData = [playInfoListData dataUsingEncoding:NSUTF8StringEncoding];
          if (playInfoData) {
            NSError *jsonError = nil;
            id jsonObject = [NSJSONSerialization JSONObjectWithData:playInfoData options:NSJSONReadingMutableContainers error:&jsonError];
            if (!jsonError && jsonObject) {
              episode[@"PlayInfoList"] = jsonObject;
              episode[@"play_info_list"] = jsonObject;
            }
          }
          episode[@"PlayInfoListData"] = playInfoListData;
          episode[@"play_info_list_data"] = playInfoListData;
        }
        [sdkEpisodeArray addObject:episode];
      } else {
        [sdkEpisodeArray addObject:episodeObj];
      }
    }
    sdkMap[@"episodes"] = sdkEpisodeArray;
  }
  
  // 使用SDK的方法创建PAGSShort对象
  PAGSShort* shortPlay = [PAGSShort pags_modelWithJSON:sdkMap];
  return shortPlay;
}

#pragma mark - 辅助方法：转换分类项为Map
- (NSDictionary*)convertCategoryItemToMap:(PAGSCategoryItem*)item {
  return @{
    @"category_id": @(item.categoryId),
    @"category_name": item.name ?: @"",
  };
}

#pragma mark - 辅助方法：创建短剧列表响应
- (NSDictionary*)createFeedListResponse:(NSArray<PAGSShort*>*)list hasMore:(BOOL)hasMore {
  NSMutableArray* shortList = [NSMutableArray array];
  for (PAGSShort* drama in list) {
    [shortList addObject:[FlutterPanglePlugin convertShortToMap:drama]];
  }
  return @{
    @"list": shortList,
    @"hasMore": @(hasMore),
  };
}

#pragma mark - 辅助方法：创建错误响应
- (FlutterError*)createErrorResponse:(NSError*)error {
  return [FlutterError errorWithCode:@"SDK_ERROR"
                             message:error.localizedDescription
                             details:@{
    @"code": @(error.code),
    @"domain": error.domain,
  }];
}

#pragma mark - 预热播放器引擎
- (void)warmUpPlayerEngine:(FlutterResult)result {
  if (_warmUpFragment || _warmUpInProgress) {
    [FlutterPanglePlugin logText:@"[PanglePlugin] skip warm up fragment:%p inProgress:%d", _warmUpFragment, _warmUpInProgress];
    result(nil);
    return;
  }
  _warmUpInProgress = YES;
  [FlutterPanglePlugin logText:@"[PanglePlugin] warmUpPlayerEngine start"];
  
  // 使用真实短剧数据进行预热
  [PAGSSDK requestFeedListWithIndex:1 count:1 completionHandler:^(NSArray<PAGSShort *> * _Nullable list, BOOL haseMore, NSError * _Nullable error) {
    dispatch_async(dispatch_get_main_queue(), ^{
      _warmUpInProgress = NO;
      if (!list || list.count == 0) {
        [FlutterPanglePlugin logText:@"[PanglePlugin] warmUpPlayerEngine list empty"];
        result(nil);
        return;
      }
      
      PAGSShort *sampleShort = list.firstObject;
      if (!sampleShort) {
        [FlutterPanglePlugin logText:@"[PanglePlugin] warmUpPlayerEngine sampleShort nil"];
        result(nil);
        return;
      }
      
      if (!_warmUpDelegate) {
        _warmUpDelegate = [[WarmUpDelegate alloc] init];
      }
      
      PAGSDetailPageConfig *config = [PAGSDetailPageConfig customConfig];
      [config setPlaySingleItem:YES];
      [config displayProgressBar:NO];
      [config displayBottomExtraView:NO];
      [config setVideoScalingMode:PAGSVideoScalingModeAspectFill];
      
      _warmUpFragment = [PAGSSDK createDetailFragmentWithShort:sampleShort
                                                    pageConfig:config
                                                      delegate:_warmUpDelegate];
      if (!_warmUpFragment) {
        [FlutterPanglePlugin logText:@"[PanglePlugin] warmUpPlayerEngine create fragment failed"];
        result(nil);
        return;
      }
      
      UIView<PAGSPPlayerViewProtocol> *playView = [_warmUpFragment playView];
      if (!playView) {
        [FlutterPanglePlugin logText:@"[PanglePlugin] warmUpPlayerEngine playView nil"];
        _warmUpFragment = nil;
        result(nil);
        return;
      }
      
      UIWindow *keyWindow = FlutterPanglePluginGetKeyWindow();
      if (!keyWindow) {
        _warmUpFragment = nil;
        result(nil);
        return;
      }
      
      UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
      container.hidden = YES;
      container.clipsToBounds = YES;
      [keyWindow addSubview:container];
      [container addSubview:playView];
      playView.frame = container.bounds;
      [FlutterPanglePlugin logText:@"[PanglePlugin] warmUpPlayerEngine start play fragment:%p", _warmUpFragment];
      
      // 激活Fragment，触发引擎初始化
      [_warmUpFragment setCurrentFragment:YES];
      [_warmUpFragment startPlay];
      
      // 延迟清理预热资源
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (_warmUpFragment) {
          [_warmUpFragment pausePlay];
          [_warmUpFragment stopPlay];
          [FlutterPanglePlugin logText:@"[PanglePlugin] warmUpPlayerEngine cleanup fragment:%p", _warmUpFragment];
          _warmUpFragment = nil;
        }
        [playView removeFromSuperview];
        [container removeFromSuperview];
        [FlutterPanglePlugin logText:@"[PanglePlugin] warmUpPlayerEngine cleanup done"];
      });
      
      result(nil);
    });
  }];
}

#pragma mark - Fragment 管理
+ (PAGSDetailFragment*)createFragmentForViewId:(int64_t)viewId
                                          short:(PAGSShort*)shortPlay
                                         config:(PAGSDetailPageConfig*)config
                                       delegate:(id<PAGSDetailFragmentDelegate, PAGSAdDelegate>)delegate {
  if (!shortPlay || !config) {
    return nil;
  }
  NSNumber *key = @(viewId);
  PAGSDetailFragment *existing = _fragmentInfo[key];
  if (existing) {
    [FlutterPanglePlugin logText:@"[PanglePlugin] replace fragment for viewId:%lld existing:%p", viewId, existing];
    [existing stopPlay];
    [_fragmentInfo removeObjectForKey:key];
  }
  PAGSDetailFragment *fragment = [PAGSSDK createDetailFragmentWithShort:shortPlay
                                                             pageConfig:config
                                                               delegate:delegate];
  if (fragment) {
    _fragmentInfo[key] = fragment;
    [FlutterPanglePlugin logText:@"[PanglePlugin] store fragment for viewId:%lld fragment:%p total:%lu", viewId, fragment, (unsigned long)_fragmentInfo.count];
  }
  return fragment;
}

+ (void)removeFragmentForViewId:(int64_t)viewId {
  NSNumber *key = @(viewId);
  PAGSDetailFragment *fragment = _fragmentInfo[key];
  if (fragment) {
    [FlutterPanglePlugin logText:@"[PanglePlugin] remove fragment viewId:%lld fragment:%p", viewId, fragment];
    [fragment stopPlay];
    [_fragmentInfo removeObjectForKey:key];
    [FlutterPanglePlugin logText:@"[PanglePlugin] fragmentInfo count after remove:%lu", (unsigned long)_fragmentInfo.count];
  }
}

+ (PAGSDetailFragment*)fragmentForViewId:(int64_t)viewId {
  PAGSDetailFragment *fragment = _fragmentInfo[@(viewId)];
  [FlutterPanglePlugin logText:@"[PanglePlugin] query fragment viewId:%lld result:%p", viewId, fragment];
  return fragment;
}

+ (void)logText:(NSString*)format, ... {
  if (!format || format.length == 0) {
    return;
  }
  va_list args;
  va_start(args, format);
  NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
  va_end(args);
//  NSLog(@"%@", message);
}

@end

